home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
jwpsrc.zip
/
MEMORY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-31
|
11KB
|
481 lines
/* Copyright (C) Stephen Chung, 1991-1993. All rights reserved. */
#include "jwp.h"
#define MAGIC 0x42022667L
typedef struct MemoryStruct {
long int magic;
void far *page;
unsigned int size;
BOOL allocated;
struct MemoryStruct far *next, far *prev;
} MEMHEADER;
typedef struct PageHeaderStruct {
long int magic;
HANDLE handle;
unsigned int size;
unsigned int used;
unsigned int overhead;
MEMHEADER far *data, far *empty;
struct PageHeaderStruct far *next, far *prev;
} MEMPAGEHEADER;
typedef struct {
MEMPAGEHEADER far *pages;
int nr_pages;
} MAINMEMHEADER;
#define PAGESIZE (4 * 1024)
#define USEABLESIZE (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))
static MAINMEMHEADER header = { NULL, 0 };
static BOOL NoErrors = FALSE;
void EnableNullPointers (BOOL enable)
{
NoErrors = enable;
}
/* Make room by trimming off undo's */
static BOOL MakeRoom (void)
{
FILEOPTIONS *f, *f1;
UNDOBUF far *up;
int largest;
void far *ptr;
largest = -1;
for (f = fileoptions; f != NULL; f = f->next) {
if (f->undo != NULL && f->undolevels > largest) {
largest = f->undolevels;
f1 = f;
}
}
if (largest < 0) return (FALSE);
/* Start trimming */
up = f1->undotail->prev;
FreeUndo(f1->undotail);
f1->undolevels--;
if (up != NULL) up->next = NULL;
if (up == NULL) {
f1->undo = f1->undotail = NULL;
f1->undolevels = 0;
}
return (TRUE);
}
static MEMPAGEHEADER far *AddPage(unsigned int n)
{
void far *cp;
MEMHEADER far *mp;
MEMPAGEHEADER far *p;
HANDLE handle = NULL;
handle = GlobalAlloc(GHND, n);
if (handle == NULL) return (NULL);
if (header.pages == NULL || header.nr_pages <= 0) {
p = header.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
p->prev = NULL;
} else {
for (p = header.pages; p->next != NULL; p = p->next);
p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
p->next->prev = p;
p = p->next;
}
p->magic = MAGIC;
p->handle = handle;
p->next = NULL;
p->size = n;
p->used = 0;
p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
mp = (MEMHEADER far *) cp;
p->data = p->empty = mp;
mp->magic = 0L;
mp->allocated = FALSE;
mp->page = p;
mp->size = p->size - p->overhead;
mp->next = mp->prev = NULL;
header.nr_pages++;
return (p);
}
static void DeletePage (MEMPAGEHEADER far *p)
{
if (p->next == NULL && p->prev == NULL) {
header.pages = NULL;
header.nr_pages = 0;
if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
}
} else {
if (p == header.pages) header.pages = p->next;
header.nr_pages--;
if (p->prev != NULL) p->prev->next = p->next;
if (p->next != NULL) p->next->prev = p->prev;
if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
}
}
}
void far *SegHeapAlloc (unsigned int n)
{
MEMPAGEHEADER far *p = NULL;
MEMHEADER far *mp;
char far *cp;
if (n >= 65535) {
ErrorMessage(global.hwnd, "SegHeapAlloc: size (%u) > 64K!\n\n"
"The program is not stable. You should save your work NOW!",
n);
n = C64K;
}
/* Larger than page size? */
if (n > USEABLESIZE) {
for (;;) {
p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
if (p != NULL) break;
if (NoErrors) return (NULL);
if (MakeRoom()) continue;
if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
return (NULL);
}
mp = p->data;
mp->magic = MAGIC;
mp->allocated = TRUE;
mp->next = mp->prev = NULL;
p->used = n;
p->empty = NULL;
cp = ((char far *) mp) + sizeof(MEMHEADER);
_fmemset(cp, 0, n);
return ((void far *) cp);
}
LookForHole:
/* Search for the hole */
for (p = header.pages; p != NULL; p = p->next) {
/* Scan the chains */
if (p->size - p->used - p->overhead <= 0) continue;
if (p->empty == NULL) continue;
for (mp = p->empty; mp != NULL; mp = mp->next) {
if (!mp->allocated && mp->size >= n) break;
}
if (mp != NULL) break;
}
/* New page needed? */
if (p == NULL) {
for (;;) {
p = AddPage(PAGESIZE);
if (p != NULL) break;
if (NoErrors) return (NULL);
if (MakeRoom()) goto LookForHole;
if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
return (NULL);
}
mp = p->data;
}
/* Do we need to break it up? */
if (mp->size - n > sizeof(MEMHEADER)) {
MEMHEADER far *mp2;
cp = ((char far *) mp) + n + sizeof(MEMHEADER);
mp2 = (MEMHEADER far *) cp;
mp2->magic = 0L;
mp2->allocated = FALSE;
mp2->page = p;
mp2->size = mp->size - n - sizeof(MEMHEADER);
mp2->next = mp->next;
mp2->prev = mp;
if (mp->next != NULL) mp->next->prev = mp2;
mp->next = mp2;
p->overhead += sizeof(MEMHEADER);
mp->size = n;
}
mp->magic = MAGIC;
mp->allocated = TRUE;
p->used += n;
cp = ((char far *) mp) + sizeof(MEMHEADER);
/* Search for the next empty hole */
for (; mp != NULL; mp = mp->next) {
if (!mp->allocated && mp->size > 0) break;
}
p->empty = mp;
_fmemset(cp, 0, n);
return ((void far *) cp);
}
void SegHeapFree (void far *vp)
{
MEMPAGEHEADER far *p;
MEMHEADER far *mp, far *mp2;
char far *cp;
cp = ((char far *) vp) - sizeof(MEMHEADER);
mp = (MEMHEADER far *) cp;
if (mp->magic != MAGIC || !mp->allocated) {
ErrorMessage(global.hwnd, "Trying to deallocate invalid memory block [%Fp, %u byte%s]!\n\n"
"The program is not stable. You should save your work NOW!",
vp, mp->size, (mp->size > 1) ? "s" : "");
return;
}
p = (MEMPAGEHEADER far *) mp->page;
p->used -= mp->size;
mp->magic = 0L;
mp->allocated = FALSE;
/* Merge? */
mp2 = mp->prev;
if (mp2 != NULL && !mp2->allocated) {
mp2->next = mp->next;
if (mp->next != NULL) mp->next->prev = mp2;
mp2->size += mp->size + sizeof(MEMHEADER);
p->overhead -= sizeof(MEMHEADER);
mp = mp2;
}
mp2 = mp->next;
if (mp2 != NULL && !mp2->allocated) {
mp->next = mp2->next;
if (mp2->next != NULL) mp2->next->prev = mp;
mp->size += mp2->size + sizeof(MEMHEADER);
p->overhead -= sizeof(MEMHEADER);
}
if (mp->prev == NULL && mp->next == NULL) {
DeletePage(p);
} else {
if (p->empty == NULL || mp < p->empty) p->empty = mp;
}
}
void far *SegHeapRealloc (void far *p, unsigned int n)
{
MEMHEADER far *mp;
char far *cp;
/* Block already large enough? */
cp = ((char far *) p) - sizeof(MEMHEADER);
mp = (MEMHEADER far *) cp;
if (mp->magic != MAGIC) {
ErrorMessage(global.hwnd, "Trying to reallocate invalid memory block [%Fp, %u byte%s]!\n\n"
"The program is not stable. You should save your work NOW!",
p, mp->size, (mp->size > 1) ? "s" : "");
/* Minimize the damage */
cp = SegHeapAlloc(n);
if (cp == NULL) return (NULL);
_fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
return (cp);
}
if (mp->size >